using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using ProjectEuler.Core.Helpers;

namespace ProjectEuler.Core
{
    public class Problem14 : IProjectEulerProblem
    {
        public int Number
        {
            get { return 14; }
        }

        protected IDictionary<long, long> GetNumberAndChainSizes()
        {
            var dict = new Dictionary<long, long>();
            for (int i = 999999; i > 500000; i--)
            {
                dict.Add(i, Chain(i).Count);
            }
            return dict;
        }

        protected IList<long> Chain(long n)
        {
            var chain = new List<long>();
            while (n != 1)
            {
                chain.Add(n);
                if (MathHelper.IsEven(n))
                {
                    n = n/2;
                }
                else
                {
                    n = (3*n) + 1;
                }
            }
            chain.Add(1);
            return chain;
        }

        public string Description
        {
            get { return "Which starting number, under one million, produces the longest chain?"; }
        }

        public string Answer
        {
            get { return GetNumberAndChainSizes().OrderByDescending(x => x.Value).First().Key.ToString(); }
        }
    }

    [TestFixture]
    public class Problem14Tests : Problem14
    {
        [Test]
        public void A_chain_for_13_contains_10_terms()
        {
            Assert.AreEqual(10, Chain(13).Count);
        }

        [Test]
        public void A_chain_for_999167_contains_321_terms()
        {
            var result = Chain(999167);
            Assert.AreEqual(321, result.Count);
        }
    }

}